#!/usr/bin/env python
# encoding: utf-8


# -- Search
# % (\w*) (\w*) coefficients:\n(c = [^%]*)\n\n

# -- Replace
# class $1$2?(ImplicitRungeKutta):
# 	"""
# 	The ?rd order $1 $2 method. 
# 	"""
# 	name = "$1 $2-?"
# 	def __init__(self,f,*args,**kwargs):
# 		$3
# 		super($1$2?, self).__init__(f,array(A),array(b),*args,**kwargs)
# 	



# --  2-stage formulas --

class Gauss_4(ImplicitRungeKutta):
	"""
	The 4th order Gauss  method. 
	"""
	name = "Gauss-4"
	def __init__(self,f,*args,**kwargs):
		c = [1/2.-sqrt(3)/6., 1/2.+sqrt(3)/6.]
		b = [1/2., 1/2.]
		A = [[1/4., 1/4.-sqrt(3)/6.],[1/4.+sqrt(3)/6., 1/4.]]
		super(Gauss_4, self).__init__(f,array(A),array(b),*args,**kwargs)
	

class RadauIIA_3(ImplicitRungeKutta):
	"""
	The 3rd order Radau IIA method. 
	"""
	name = "Radau IIA-3"
	def __init__(self,f,*args,**kwargs):
		c = [1/3., 1]
		b = [3/4., 1/4.]
		A = [[5/12., -1/12.],[9/12., 3/12.]]
		super(RadauIIA_3, self).__init__(f,array(A),array(b),*args,**kwargs)
	

class LobattoIIIA_2(ImplicitRungeKutta):
	"""
	The 2nd order Lobatto IIIA method. 
	"""
	name = "Lobatto IIIA-2"
	def __init__(self,f,*args,**kwargs):
		c = [0, 1]
		b = [1/2., 1/2.]
		A = [[0, 0],[1/2., 1/2.]]
		super(LobattoIIIA_2, self).__init__(f,array(A),array(b),*args,**kwargs)
	

class LobattoIIIB_2(ImplicitRungeKutta):
	"""
	The 2nd order Lobatto IIIB method. 
	"""
	name = "Lobatto IIIB-2"
	def __init__(self,f,*args,**kwargs):
		c = [1/2., 1/2.]
		b = [1/2., 1/2.]
		A = [[1/2., 0],[1/2., 0]]
		super(LobattoIIIB_2, self).__init__(f,array(A),array(b),*args,**kwargs)
	

class LobattoIIIC_2(ImplicitRungeKutta):
	"""
	The 2nd order Lobatto IIIC method. 
	"""
	name = "Lobatto IIIC-2"
	def __init__(self,f,*args,**kwargs):
		c = [0, 1]
		b = [1/2., 1/2.]
		A = [[1/2., -1/2.],[1/2., 1/2.]]
		
		super(LobattoIIIC_2, self).__init__(f,array(A),array(b),*args,**kwargs)
	

class LobattoIIICstar_2(ImplicitRungeKutta):
	"""
	The 2nd order Lobatto IIIC* method. 
	"""
	name = "Lobatto IIIC*-2"
	def __init__(self,f,*args,**kwargs):
		c = [0, 1]
		b = [1/2., 1/2.]
		A = [[0, 0],[1, 0]]
		super(LobattoIIICstar_2, self).__init__(f,array(A),array(b),*args,**kwargs)
	

class LobattoIIID_2(ImplicitRungeKutta):
	"""
	The 2nd order Lobatto IIID method. 
	"""
	name = "Lobatto IIID-2"
	def __init__(self,f,*args,**kwargs):
		s1 = LobattoIIIC_2(f)
		s2 = LobattoIIICstar_2(f)
		b = s1.b
		A = (s1.A+s2.A)/2.
		super(LobattoIIID_2, self).__init__(f,array(A),array(b),*args,**kwargs)
	


# --  3-stage formulas --

class RadauI_5(ImplicitRungeKutta):
	"""
	The 5th order Radau I method. 
	"""
	name = "Radau I-5"
	def __init__(self,f,*args,**kwargs):
		c = [0, (6-sqrt(6))/10., (6+sqrt(6))/10.]
		b = [1/9., (16+sqrt(6))/36., (16-sqrt(6))/36.]
		A = [[0, 0, 0], \
			[(9+sqrt(6))/75., (24+sqrt(6))/120., (168-73*sqrt(6))/600.], \
			[(9-sqrt(6))/75., (168+73*sqrt(6))/600., (24-sqrt(6))/120.]]
		super(RadauI_5, self).__init__(f,array(A),array(b),*args,**kwargs)
	

class RadauIA_5(ImplicitRungeKutta):
	"""
	The 5th order Radau IA method. 
	"""
	name = "Radau IA-5"
	def __init__(self,f,*args,**kwargs):
		c = [0, (6-sqrt(6))/10., (6+sqrt(6))/10.]
		b = [1/9., (16+sqrt(6))/36., (16-sqrt(6))/36.]
		A = [[1/9., -(1+sqrt(6))/18., -(1-sqrt(6))/18.], \
			[1/9., (88+7*sqrt(6))/360., (88-43*sqrt(6))/360.], \
			[1/9., (88+43*sqrt(6))/360., (88-7*sqrt(6))/360.]]
		super(RadauIA_5, self).__init__(f,array(A),array(b),*args,**kwargs)
	

class RadauII_5(ImplicitRungeKutta):
	"""
	The 5th order Radau II method. 
	"""
	name = "Radau II-5"
	def __init__(self,f,*args,**kwargs):
		c = [(4-sqrt(6))/10., (4+sqrt(6))/10., 1]
		b = [(16-sqrt(6))/36., (16+sqrt(6))/36., 1/9.]
		A = [[(24-sqrt(6))/120., (24-11*sqrt(6))/120., 0], \
			[(24+11*sqrt(6))/120., (24+sqrt(6))/120., 0], \
			[(6-sqrt(6))/12., (6+sqrt(6))/12., 0]]
		super(RadauII_5, self).__init__(f,array(A),array(b),*args,**kwargs)
	

class RadauIIA_5(ImplicitRungeKutta):
	"""
	The 5th order Radau IIA method. 
	"""
	name = "Radau IIA-5"
	def __init__(self,f,*args,**kwargs):
		c = [(4-sqrt(6))/10., (4+sqrt(6))/10., 1]
		b = [(16-sqrt(6))/36., (16+sqrt(6))/36., 1/9.]
		A = [[(88-7*sqrt(6))/360., (296-169*sqrt(6))/1800., (-2+3*sqrt(6))/225.], \
			[(296+169*sqrt(6))/1800., (88+7*sqrt(6))/360., (-2-3*sqrt(6))/225.], \
			[(16-sqrt(6))/36., (16+sqrt(6))/36., 1/9.]]
		super(RadauIIA_5, self).__init__(f,array(A),array(b),*args,**kwargs)
	

class Gauss_6(ImplicitRungeKutta):
	"""
	The 6th order Gauss method. 
	"""
	name = "Gauss-6"
	def __init__(self,f,*args,**kwargs):
		c = [0.5-sqrt(15)/10., 0.5, 0.5+sqrt(15)/10.]
		b = array([5, 8, 5])/18.
		A = [[5/36., 2/9.-sqrt(15)/15., 5/36.-sqrt(15)/30.], \
			[5/36.+sqrt(15)/24., 2/9., 5/36.-sqrt(15)/24.], \
			[5/36.+sqrt(15)/30., 2/9.+sqrt(15)/15., 5/36.]]
		super(Gauss_6, self).__init__(f,array(A),array(b),*args,**kwargs)
	

class LobattoIIIA_4(ImplicitRungeKutta):
	"""
	The 4th order Lobatto IIIA method. 
	"""
	name = "Lobatto IIIA-4"
	def __init__(self,f,*args,**kwargs):
		c = [0, 0.5, 1]
		b = [1/6., 2/3., 1/6.]
		A = [[0, 0, 0],[5/24., 1/3., -1/24.],[1/6., 2/3., 1/6.]]
		super(LobattoIIIA_4, self).__init__(f,array(A),array(b),*args,**kwargs)
	

class LobattoIIIB_4(ImplicitRungeKutta):
	"""
	The 4th order Lobatto IIIB method. 
	"""
	name = "Lobatto IIIB-4"
	def __init__(self,f,*args,**kwargs):
		c = [0, 0.5, 1]
		b = [1/6., 2/3., 1/6.]
		A = [[1/6., -1/6., 0],[1/6., 1/3., 0],[1/6., 5/6., 0]]
		super(LobattoIIIB_4, self).__init__(f,array(A),array(b),*args,**kwargs)
	

class LobattoIIIC_4(ImplicitRungeKutta):
	"""
	The 4th order Lobatto IIIC method. 
	"""
	name = "Lobatto IIIC-4"
	def __init__(self,f,*args,**kwargs):
		c = [0, 0.5, 1]
		b = [1/6., 2/3., 1/6.]
		A = [[1/6., -1/3., 1/6.],[1/6., 5/12., -1/12.],[1/6., 2/3., 1/6.]]
		
		super(LobattoIIIC_4, self).__init__(f,array(A),array(b),*args,**kwargs)
	

class LobattoIIICstar_4(ImplicitRungeKutta):
	"""
	The 4th order Lobatto IIIC* method. 
	"""
	name = "Lobatto IIIC*-4"
	def __init__(self,f,*args,**kwargs):
		c = [0, 0.5, 1]
		b = [1/6., 2/3., 1/6.]
		A = [[0, 0, 0],[1/4., 1/4., 0],[0, 1, 0]]
		super(LobattoIIICstar_4, self).__init__(f,array(A),array(b),*args,**kwargs)
	

class LobattoIIID_4(ImplicitRungeKutta):
	"""
	The 4th order Lobatto IIID method. 
	"""
	name = "Lobatto IIID-4"
	def __init__(self,f,*args,**kwargs):
		s1 = LobattoIIIC_4(f)
		s2 = LobattoIIICstar_4(f)
		b = s1.b
		A = (s1.A+s2.A)/2.
		super(LobattoIIID_4, self).__init__(f,array(A),array(b),*args,**kwargs)
	


# --  4-stage formulas --

class LobattoIIIA_6(ImplicitRungeKutta):
	"""
	The 6th order Lobatto IIIA method. 
	"""
	name = "Lobatto IIIA-6"
	def __init__(self,f,*args,**kwargs):
		c = [0, (5-sqrt(5))/10., (5+sqrt(5))/10., 1]
		b = [1/12., 5/12., 5/12., 1/12.]
		A = [[0, 0, 0, 0], \
			[(11+sqrt(5))/120., (25-sqrt(5))/120., (25-13*sqrt(5))/120., (-1+sqrt(5))/120.], \
			[(11-sqrt(5))/120., (25+13*sqrt(5))/120., (25+sqrt(5))/120., (-1-sqrt(5))/120.], \
			[1/12., 5/12., 5/12., 1/12.]]
		super(LobattoIIIA_6, self).__init__(f,array(A),array(b),*args,**kwargs)
	

class LobattoIIIB_6(ImplicitRungeKutta):
	"""
	The 6th order Lobatto IIIB method. 
	"""
	name = "Lobatto IIIB-6"
	def __init__(self,f,*args,**kwargs):
		c = [0, (5-sqrt(5))/10., (5+sqrt(5))/10., 1]
		b = [1/12., 5/12., 5/12., 1/12.]
		A = [[1/12., (-1-sqrt(5))/24., (-1+sqrt(5))/24., 0], \
			[1/12., (25+sqrt(5))/120., (25-13*sqrt(5))/120., 0], \
			[1/12., (25+13*sqrt(5))/120., (25-sqrt(5))/120., 0], \
			[1/12., (11-sqrt(5))/120., (11+sqrt(5))/120., 0]]
		super(LobattoIIIB_6, self).__init__(f,array(A),array(b),*args,**kwargs)
	

class LobattoIIIC_6(ImplicitRungeKutta):
	"""
	The 6th order Lobatto IIIC method. 
	"""
	name = "Lobatto IIIC-6"
	def __init__(self,f,*args,**kwargs):
		c = [0, (5-sqrt(5))/10., (5+sqrt(5))/10., 1]
		b = [1/12., 5/12., 5/12., 1/12.]
		A = [[1/12., -sqrt(5)/12., sqrt(5)/12., -1/12.], \
			[1/12., 1/4., (10-7*sqrt(5))/60., sqrt(5)/60.], \
			[1/12., (10+7*sqrt(5))/60., 1/4., -sqrt(5)/60.], \
			[1/12., 5/12., 5/12., 1/12.]]
		super(LobattoIIIC_6, self).__init__(f,array(A),array(b),*args,**kwargs)
	

class LobattoIIICstar_6(ImplicitRungeKutta):
	"""
	The 6th order Lobatto IIIC* method. 
	"""
	name = "Lobatto IIIC*-6"
	def __init__(self,f,*args,**kwargs):
		c = [0, (5-sqrt(5))/10., (5+sqrt(5))/10., 1]
		b = [1/12., 5/12., 5/12., 1/12.]
		A = [[0, 0, 0, 0], \
			[(5+sqrt(5))/60., 1/6., (15-7*sqrt(5))/60., 0], \
			[(5-sqrt(5))/60., (15+7*sqrt(5))/60., 1/6., 0], \
			[1/6., (5-sqrt(5))/12., (5+sqrt(5))/12., 0]]
		super(LobattoIIICstar_6, self).__init__(f,array(A),array(b),*args,**kwargs)
	

class LobattoIIID_6(ImplicitRungeKutta):
	"""
	The 6th order Lobatto IIID method. 
	"""
	name = "Lobatto IIID-6"
	def __init__(self,f,*args,**kwargs):
		s1 = LobattoIIIC_6(f)
		s2 = LobattoIIICstar_6(f)
		b = s1.b
		A = (s1.A+s2.A)/2.
		super(LobattoIIID_6, self).__init__(f,array(A),array(b),*args,**kwargs)
	



# --  5-stage formulas --

class LobattoIIIA_8(ImplicitRungeKutta):
	"""
	The 8th order Lobatto IIIA method. 
	"""
	name = "Lobatto IIIA-8"
	def __init__(self,f,*args,**kwargs):
		c = [0, (7-sqrt(21))/14., 1/2., (7+sqrt(21))/14., 1]
		b = [1/20., 49/180., 16/45., 49/180., 1/20.]
		A = [[0, 0, 0, 0, 0], \
			[(119+3*sqrt(21))/1960., (343-9*sqrt(21))/2520., (392-96*sqrt(21))/2205., (343-69*sqrt(21))/2520., (-21+3*sqrt(21))/1960.], \
			[13/320., (392+105*sqrt(21))/2880., 8/45., (392-105*sqrt(21))/2880., 3/320.], \
			[(119-3*sqrt(21))/1960., (343+69*sqrt(21))/2520., (392+96*sqrt(21))/2205., (343+9*sqrt(21))/2520., (-21-3*sqrt(21))/1960.], \
			[1/20., 49/180., 16/45., 49/180., 1/20.]]
		super(LobattoIIIA_8, self).__init__(f,array(A),array(b),*args,**kwargs)
	

class LobattoIIIB_8(ImplicitRungeKutta):
	"""
	The 8th order Lobatto IIIB method. 
	"""
	name = "Lobatto IIIB-8"
	def __init__(self,f,*args,**kwargs):
		c = [0, (7-sqrt(21))/14., 1/2., (7+sqrt(21))/14., 1]
		b = [1/20., 49/180., 16/45., 49/180., 1/20.]
		A = [[1/20., (-7-sqrt(21))/120., 1/15., (-7+sqrt(21))/120., 0], \
			[1/20., (343+9*sqrt(21))/2520., (56-15*sqrt(21))/315., (343-69*sqrt(21))/2520., 0], \
			[1/20., (49+12*sqrt(21))/360., 8/45., (49-12*sqrt(21))/360., 0], \
			[1/20., (343+69*sqrt(21))/2520., (56+15*sqrt(21))/315., (343-9*sqrt(21))/2520., 0], \
			[1/20., (119-3*sqrt(21))/360., 13/45., (119+3*sqrt(21))/360., 0]]
		super(LobattoIIIB_8, self).__init__(f,array(A),array(b),*args,**kwargs)
	

class LobattoIIIC_8(ImplicitRungeKutta):
	"""
	The 8th order Lobatto IIIC method. 
	"""
	name = "Lobatto IIIC-8"
	def __init__(self,f,*args,**kwargs):
		c = [0, (7-sqrt(21))/14., 1/2., (7+sqrt(21))/14., 1]
		b = [1/20., 49/180., 16/45., 49/180., 1/20.]
		A = [[1/20., -7/60., 2/15., -7/60., 1/20.], \
			[1/20., 29/180., (47-15*sqrt(21))/315., (203-30*sqrt(21))/1260., -3/140.], \
			[1/20., (329+105*sqrt(21))/2880., 73/360., (329-105*sqrt(21))/2880., 3/160.], \
			[1/20., (203+30*sqrt(21))/1260., (47+15*sqrt(21))/315., 29/180., -3/140.], \
			[1/20., 49/180., 16/45., 49/180., 1/20.]]
		super(LobattoIIIC_8, self).__init__(f,array(A),array(b),*args,**kwargs)
	

class LobattoIIICstar_8(ImplicitRungeKutta):
	"""
	The 8th order Lobatto IIIC* method. 
	"""
	name = "Lobatto IIIC*-8"
	def __init__(self,f,*args,**kwargs):
		c = [0, (7-sqrt(21))/14., 1/2., (7+sqrt(21))/14., 1]
		b = [1/20., 49/180., 16/45., 49/180., 1/20.]
		A = [[0, 0, 0, 0, 0], \
			[1/14., 1/9., (13-3*sqrt(21))/63., (14-3*sqrt(21))/126., 0], \
			[1/32., (91+21*sqrt(21))/576., 11/72., (91-21*sqrt(21))/576., 0], \
			[1/14., (14+3*sqrt(21))/126., (13+3*sqrt(21))/63., 1/9., 0], \
			[0, 7/18., 2/9., 7/18., 0]]
		super(LobattoIIICstar_8, self).__init__(f,array(A),array(b),*args,**kwargs)
	

class LobattoIIID_8(ImplicitRungeKutta):
	"""
	The 8th order Lobatto IIID method. 
	"""
	name = "Lobatto IIID-8"
	def __init__(self,f,*args,**kwargs):
		s1 = LobattoIIIC_8(f)
		s2 = LobattoIIICstar_8(f)
		b = s1.b
		A = (s1.A+s2.A)/2.
		super(LobattoIIID_8, self).__init__(f,array(A),array(b),*args,**kwargs)
	

